/*
 * Copyright (c) 2012 SUBSECRETARIA DEFENSORIA DEL ESPACIO PUBLICO - SDEP.
 * All Rights Reserved.
 * This software is the confidential and proprietary information of SDEP
 * Developed By CONSTULT-SOFT S.A, Development Team 2012.
 *
 */
package co.gov.medellin.sdep.sisdep.domain.operativa;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.faces.model.SelectItem;

import co.gov.medellin.sdep.sisdep.common.AppConstants;
import co.gov.medellin.sdep.sisdep.common.OracleHelper;
import co.gov.medellin.sdep.sisdep.common.dto.GenericComponentVO;
import co.gov.medellin.sdep.sisdep.common.dto.GenericComponentValueVO;
import co.gov.medellin.sdep.sisdep.common.enums.OperativoStatusEnum;
import co.gov.medellin.sdep.sisdep.domain.BaseController;
import co.gov.medellin.sdep.sisdep.domain.MessageModalWindowController;
import co.gov.medellin.sdep.sisdep.integration.mapasmedellin.BeanDireccion;
import co.gov.medellin.sdep.sisdep.integration.mapasmedellin.GeoUbicacionClient;
import co.gov.medellin.sdep.sisdep.model.Operativo;
import co.gov.medellin.sdep.sisdep.operativa.exception.OperativoException;
import co.gov.medellin.sdep.sisdep.operativa.exception.OperativoRuntimeException;
import co.gov.medellin.sdep.sisdep.operativa.service.IOperativoService;

/**
 * <p>
 * Clase controladora que permite realizar el proceso de gestion de Operativos.
 * Permite al usuario realizar operaciones de consulta, creacion y actualizacion de registros.
 * </p>
 * <p>
 * Copyright (c) 2012<BR>
 * Consult-Soft S.A.<BR>
 * Created on: Jul 03, 2012<BR>
 * 
 * @author atabares
 * </p>
 */
public class OperativoController extends BaseController implements Serializable {

	/** Generated serial version. */
	private static final long serialVersionUID = -3285110767384990403L;

	/** Mensaje usado en el mensaje de confirmacion en la actualizacion de operativos. */
	public static final String SEARCH_RETURN = " Desea regresar a la pantalla de Consulta de Operativos?";
	
	/** Bean para el manejo del formulario de busqueda Operativo */
	private Operativo operativoSearch = new Operativo();

	/** Objeto contenedor del listado de Operativo luego de una consulta. */
	private transient DataModel operativoListModel;

	/** Bean para el manejo del formulario de creacion/edicion. Operativo */
	private Operativo operativo = new Operativo();
	
	/** Lista con los recursos humanos disponibles en SISDEP. */
	private List recursoHumanoList;

	/** Instancia de servicio operativoService */
	private IOperativoService operativoService;
	
	/** Objeto cliente para el manejo los Barrios y Comunas dados por MapasMedellin. */
	private GeoUbicacionClient geoUbicacionClient;
	
	/** instancia un objeto de direccion local, en caso que el usuario no valide direccion al menos una vez */
	private BeanDireccion direccionLocal = new BeanDireccion();
	
	/** Lista de valores asociados al estado de un operativo - (OperativoStatusEnum). */
	private List operativoStatusList;
	
	
	/**
	 * Constructor por defecto, inicializa los elemento basicos del Controlador
	 */
	public OperativoController() {
		this.operativoListModel = new ListDataModel();
	}
	
	/**
	 * Obtiene el parametro operativoSearch.
	 * @see OperativoController#operativoSearch
	 *
	 * @return El parametro operativoSearch.
	 */
	public Operativo getOperativoSearch() {
		return operativoSearch;
	}

	/**
	 * Asigna el parametro operativoSearch.
	 * @see OperativoController#operativoSearch
	 *
	 * @param operativoSearch valor a asignar al parametro operativoSearch.
	 */
	public void setOperativoSearch(Operativo operativoSearch) {
		this.operativoSearch = operativoSearch;
	}

	/**
	 * Obtiene el parametro operativoListModel.
	 * @see OperativoController#operativoListModel
	 *
	 * @return El parametro operativoListModel.
	 */
	public DataModel getOperativoListModel() {
		return operativoListModel;
	}

	/**
	 * Asigna el parametro operativoListModel.
	 * @see OperativoController#operativoListModel
	 *
	 * @param operativoListModel valor a asignar al parametro operativoListModel.
	 */
	public void setOperativoListModel(DataModel operativoListModel) {
		this.operativoListModel = operativoListModel;
	}

	/**
	 * Obtiene el parametro operativo.
	 * @see OperativoController#operativo
	 *
	 * @return El parametro operativo.
	 */
	public Operativo getOperativo() {
		return operativo;
	}

	/**
	 * Asigna el parametro operativo.
	 * @see OperativoController#operativo
	 *
	 * @param operativo valor a asignar al parametro operativo.
	 */
	public void setOperativo(Operativo operativo) {
		this.operativo = operativo;
	}

	/**
	* Obtiene el parametro recursoHumanoList.
	* @see OperativoController#recursoHumanoList
	*
	* @return El parametro recursoHumanoList.
	*/
	public List getRecursoHumanoList() {
		if (recursoHumanoList == null) {
			recursoHumanoList = new ArrayList();
			
			try {
				GenericComponentVO genericComponentVO = getOperativoService().getRecursoHumanoList();
				Iterator iter = genericComponentVO.getComponentValueList().iterator();
				
				while (iter.hasNext()) {
					GenericComponentValueVO genericComponentValueVO = (GenericComponentValueVO) iter.next();
					
					recursoHumanoList.add(new SelectItem(genericComponentValueVO.getComponentValueId(), 
							genericComponentValueVO.getComponentValueName()));
				}
			} catch (Exception e) {
				e.printStackTrace(System.err);

				((MessageModalWindowController) getBean(AppConstants.MESSAGE_CONTROLLER_BEAN))
						.setErrorMessage(AppConstants.DEFAULT_ERROR + e.getMessage(), null, null);
			}
		}
		
		return recursoHumanoList;
	}

	/**
	* Asigna el parametro recursoHumanoList.
	* @see OperativoController#recursoHumanoList
	*
	* @param recursoHumanoList valor a asignar al parametro recursoHumanoList.
	*/
	public void setRecursoHumanoList(List recursoHumanoList) {
		this.recursoHumanoList = recursoHumanoList;
	}

	/**
	 * Obtiene el parametro operativoService.
	 * @see OperativoController#operativoService
	 *
	 * @return El parametro operativoService.
	 */
	public IOperativoService getOperativoService() {
		return operativoService;
	}

	/**
	 * Asigna el parametro operativoService.
	 * @see OperativoController#operativoService
	 *
	 * @param operativoService valor a asignar al parametro operativoService.
	 */
	public void setOperativoService(IOperativoService operativoService) {
		this.operativoService = operativoService;
	}

	/**
	* Obtiene el parametro geoUbicacionClient.
	* @see OperativoController#geoUbicacionClient
	*
	* @return El parametro geoUbicacionClient.
	*/
	public GeoUbicacionClient getGeoUbicacionClient() {
		return geoUbicacionClient;
	}

	/**
	* Asigna el parametro geoUbicacionClient.
	* @see OperativoController#geoUbicacionClient
	*
	* @param geoUbicacionClient valor a asignar al parametro geoUbicacionClient.
	*/
	public void setGeoUbicacionClient(GeoUbicacionClient geoUbicacionClient) {
		this.geoUbicacionClient = geoUbicacionClient;
	}

	/**
	* Obtiene el parametro operativoStatusList.
	* @see OperativoController#operativoStatusList
	*
	* @return El parametro operativoStatusList.
	*/
	public List getOperativoStatusList() {
		if (operativoStatusList == null) {
			operativoStatusList = new ArrayList();
			
			try {
				Iterator iter = OperativoStatusEnum.VALUES.iterator();
				
				while (iter.hasNext()) {
					OperativoStatusEnum operativoStatusEnum = (OperativoStatusEnum) iter.next();
					
					operativoStatusList.add(new SelectItem(operativoStatusEnum.toString(), operativoStatusEnum.toString()));
				}
			} catch (Exception e) {
				e.printStackTrace(System.err);

				((MessageModalWindowController) getBean(AppConstants.MESSAGE_CONTROLLER_BEAN))
						.setErrorMessage(AppConstants.DEFAULT_ERROR + e.getMessage(), null, null);
			}
		}
		
		return operativoStatusList;
	}

	/**
	* Asigna el parametro operativoStatusList.
	* @see OperativoController#operativoStatusList
	*
	* @param operativoStatusList valor a asignar al parametro operativoStatusList.
	*/
	public void setOperativoStatusList(List operativoStatusList) {
		this.operativoStatusList = operativoStatusList;
	}

	
	/**
	 * Obtiene los registros de los operativos que coinciden con los parametros de busqueda ingresados.
	 * @return La cadena que redirecciona a la pagina de resultados de busqueda de operativos.
	 */
	public String getOperativoListByParameters() {
		try {
			List operativoList = new ArrayList();
			
			operativoList = getOperativoService().getOperativoListByCriteria(this.operativoSearch);
			
			this.operativoListModel.setWrappedData(operativoList);
		} catch (Exception e) {
			e.printStackTrace(System.err);
			
			((MessageModalWindowController) getBean(AppConstants.MESSAGE_CONTROLLER_BEAN))
				.setErrorMessage(AppConstants.DEFAULT_ERROR + e.getMessage(), null, null);
		}
		
		if (this.operativoListModel.getWrappedData() == null 
				|| ((List) this.operativoListModel.getWrappedData()).isEmpty()) {
			
			((MessageModalWindowController) getBean(AppConstants.MESSAGE_CONTROLLER_BEAN))
				.setAlertMessage(AppConstants.NO_RECORDS_FOUND, null, null);
		}
		
		return AppConstants.OPERATIVO_SEARCH_VIEW;
	}

	/**
	 * Ajusta los parametros para la creacion de un nuevo registro de operativo.
	 * @return String Con la cadena que redirecciona a la pagina de creacion de operativos.
	 */
	public String manageCreate() {
		this.operativo = new Operativo();
		this.operativo.setActualizacion(false);
		
		return AppConstants.OPERATIVO_CREATE_VIEW;
	}
	
	/**
	 * Ajusta los parametros para la actualizacion de un registro de operativo.
	 * @return String Con la cadena que redirecciona a la pagina de actualizacion de operativos.
	 */
	public String manageUpdate() {
		Map params = getExternalContext().getRequestParameterMap();
		String operativoDataIndex = (String) params.get("operativoDataIndex");
		List operativoListTemp = (List) this.operativoListModel.getWrappedData();
		
		Long idOperativo = ((Operativo) operativoListTemp.get(Integer.parseInt(operativoDataIndex))).getId();
		
		try {
			this.operativo = getOperativoService().get(idOperativo.longValue());
			
			this.operativo.setActualizacion(true);
		} catch (OperativoException e) {
			e.printStackTrace(System.err);
			
			((MessageModalWindowController) getBean(AppConstants.MESSAGE_CONTROLLER_BEAN))
				.setErrorMessage(AppConstants.DEFAULT_ERROR + e.getEndUserMessage(), null, null);
		}
		
		return AppConstants.OPERATIVO_UPDATE_VIEW;
	}
	
	/**
	 * Ajusta las propiedades de Operativos e invoca los metodos necesarios para su insercion en DB.
	 * @return La cadena que redirecciona a la pagina de creacion de Operativos.
	 */
	public String create() {
		this.checkAddress();
		this.operativo.setEstado(OperativoStatusEnum.PROGRAMMED.toString());
		this.operativo.setUsuarioCrea(BaseController.getLoggedUserID());
		
		String msg = null;
		
		try {
			getOperativoService().insert(this.operativo);
			
			((MessageModalWindowController) getBean(AppConstants.MESSAGE_CONTROLLER_BEAN))
				.setSuccessMessage(AppConstants.SUCCESS_CREATE, null, null);
			
			this.operativo = new Operativo();
		} catch (OperativoException e) {
			e.printStackTrace(System.err);
			
			((MessageModalWindowController) getBean(AppConstants.MESSAGE_CONTROLLER_BEAN))
				.setErrorMessage(AppConstants.DEFAULT_ERROR + e.getEndUserMessage(), null, null);
		} catch (OperativoRuntimeException e) {
			e.printStackTrace(System.err);
			
			((MessageModalWindowController) getBean(AppConstants.MESSAGE_CONTROLLER_BEAN))
				.setErrorMessage(AppConstants.DEFAULT_ERROR + e.getEndUserMessage(), null, null);
		}
		
		return AppConstants.MODULO_CREATE_VIEW;
	}
	
	/**
	 * Ajusta las propiedades de Modulos e invoca los metodos necesarios para su actualizacion en DB.
	 * @return La cadena que redirecciona a la pagina de actualizacion de modulos.
	 */
	public String update() {
		this.checkAddress();
		
		try {
			if (this.operativo.getId().longValue() != 0L) {
				getOperativoService().update(this.operativo);
				
				getOperativoListByParameters();
				
				((MessageModalWindowController) getBean(AppConstants.MESSAGE_CONTROLLER_BEAN))
					.setConfirmMessage(AppConstants.SUCCESS_UPDATE + OperativoController.SEARCH_RETURN, 
						MessageModalWindowController.ACTION_NAVIGATE, AppConstants.OPERATIVO_SEARCH_VIEW, 
							AppConstants.OPERATIVO_UPDATE_VIEW);
			}
		} catch (OperativoException e) {
			e.printStackTrace(System.err);
			
			((MessageModalWindowController) getBean(AppConstants.MESSAGE_CONTROLLER_BEAN))
				.setErrorMessage(AppConstants.DEFAULT_ERROR + e.getEndUserMessage(), null, null);
		} catch (OperativoRuntimeException e) {
			e.printStackTrace(System.err);
			
			((MessageModalWindowController) getBean(AppConstants.MESSAGE_CONTROLLER_BEAN))
				.setErrorMessage(AppConstants.DEFAULT_ERROR + e.getEndUserMessage(), null, null);
		}
		
		return AppConstants.OPERATIVO_UPDATE_VIEW;
	}
	
	/**
	 * Verifica la direccion ingresada mediante el servicio web de verificacion de direcciones.
	 * @return
	 */
	public String checkAddress() {
		direccionLocal = getGeoUbicacionClient().getAddressLocalization(this.operativo.getDireccionOperativo());
		
		if(null == direccionLocal) {
			direccionLocal = new BeanDireccion();
		}
		
		this.operativo.setCodigoBarrio(OracleHelper
				.isNullorEmpty(direccionLocal.getCodBarrio()) ? "N/A" : direccionLocal.getCodBarrio());
		this.operativo.setBarrio(OracleHelper
				.isNullorEmpty(direccionLocal.getValueNomBarrio()) ? "NO Disponible" : direccionLocal.getValueNomBarrio());
		this.operativo.setCodigoComuna(OracleHelper
				.isNullorEmpty(direccionLocal.getCodComuna()) ? "N/A" : direccionLocal.getCodComuna());
		this.operativo.setComuna(OracleHelper
				.isNullorEmpty(direccionLocal.getValueNomComuna()) ? "NO Disponible" : direccionLocal.getValueNomComuna());

		return AppConstants.EMPTY;
	}
}
